package org.foreningsgatan.genetics;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

public class NodeFactory<T extends Serializable, S extends Serializable> {
	private Random random;
	protected List<S> actions;
	protected List<T> dataSources;
	
	public NodeFactory(T[] dataSources, S[] actions) {
		this.actions = Arrays.asList(actions);
		this.dataSources = Arrays.asList(dataSources);
		this.random = new Random();
	}
	
	private <R> R getRandomEntry(List<R> list) {
		int index = random.nextInt(list.size());
		
		return list.get(index);
	}
	
	protected S randomAction() {
		return getRandomEntry(actions);
	}
	
	protected T randomDataSource() {
		return getRandomEntry(dataSources);
	}
	
	private Node<T, S> newNodeRecursive(int level) {
		int type = level < 10 ? random.nextInt(3) : 0;
		
		switch (type) {
			case 0:
				S action = randomAction();
				
				return new ActionNode<T, S>(action);
			case 1:
				T dataSource = randomDataSource();
				float limit = random.nextFloat();
				
				DecisionNode<T, S> dNode = new DecisionNode<T, S>(dataSource, limit);
				dNode.leftNode = newNodeRecursive(level + 1);
				dNode.rightNode = newNodeRecursive(level + 1);
				
				return dNode;
			case 2:
				MultipleNode<T, S> mNode = new MultipleNode<T, S>();
				mNode.leftNode = newNodeRecursive(level + 1);
				mNode.rightNode = newNodeRecursive(level + 1);
				
				return mNode;
		}
		
		return null;
	}
	
	public Node<T, S> newRootNode() {
		return newNodeRecursive(1);
	}
}
